# Copyright (c) 2007 Fabio Makoto Akita
# 
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# 
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# 
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

# Author: AkitaOnRails (www.akitaonrails.com)
# Support: Surgeworks LLC (www.surgeworks.com)

#
# WARNING: DO NOT EDIT THIS FILE MANUALLY - IT IS AUTOMATICALLY GENERATED BY THE PLUGIN
#
module SyncsHelper
  module ClientActions
    MAX_ERRORS = 10
    
    private 
  
    # run the complete download procedure, with batch support. 
    # f is the log file handle
    def run_download(server_machine_id, f)
      count = begin
        do_get_server_data_count(address, server_machine_id) 
      rescue Exception => e
        f.puts "#{log_timestamp} -- DOWNLOADED AND PROCESSED: 0 RECORDS"
        f.flush
        return ActsAsReplica::Structs::SyncPayload.build_empty
      end
    
      f.puts "#{log_timestamp} --- ESTIMATED TOTAL RECORDS TO DOWNLOAD: #{count.total}"
      f.flush
      total, total_errors = 0, 0
      while total_errors < SyncsHelper::ClientActions::MAX_ERRORS
        begin
          result_up = do_get_server_data(address, server_machine_id)
          if result_up.status == 200 
            f.puts "#{log_timestamp} -- DOWNLOADED AND PROCESSED: #{total} RECORDS"
            f.flush
            result_up.total > 0 ? total += result_up.total : break
          elsif result_up.errors && result_up.errors.size > 0
            total_errors += 1 # avoid infinite loop
            f.puts "#{log_timestamp} --- WARNING FROM #{address}. ERROR: #{result_up.errors.join("\n")}"
            f.flush
          end
        rescue Exception => e
          total_errors += 1 # avoid infinite loop
          f.puts "#{log_timestamp} --- WARNING FROM #{address}. ERROR: #{e.inspect}"
          f.flush
        end
      end
      # only consider a Fatal Error if looped many times without results
      # this should flag the origin caller to stop the process and ask the user to retry
      if total_errors == SyncsHelper::ClientActions::MAX_ERRORS
        f.puts "#{log_timestamp} --- ERROR DOWNLOADING FROM #{address}. ERROR: SEE WARNINGS ABOVE"
        f.flush
      end
      total
    end
    
    # run the complete upload procedure, with batch support. 
    # server_result is the last synced id got from the server in the handshake procedure
    # f is the log file handle
    def run_upload(server_result, server_machine_id, f)
      count = Replica.down(server_result, server_machine_id, :count => true)
      f.puts "#{log_timestamp} --- ESTIMATED TOTAL RECORDS TO UPLOAD: #{count.total}"
      f.flush
      total, total_errors = 0, 0
      while total_errors < SyncsHelper::ClientActions::MAX_ERRORS
        begin
          result_down = do_send_client_data(address, server_result, server_machine_id)
          server_result = result_down.last_synced_id if result_down.respond_to?(:last_synced_id)
          if result_down.total > 0
            total += result_down.total
            f.puts "#{log_timestamp} -- UPLOADED AND PROCESSED: #{total} RECORDS"
            f.flush
          else
            break
          end
        rescue Exception => e
          total_errors += 1 # avoid infinite loop
          f.puts "#{log_timestamp} --- ERROR: CANNOT UPLOAD AT #{address}. ERROR: #{e.inspect}"
          f.flush
        end
      end
      total
    end

    def run_sync(manual_server_package = nil)
      @config = $SYNC_CONFIG    
      total_down, total_up = 0, 0
      File.open(SyncsHelper::ReplicatorRunner.log_file, 'a') do |f|
        start_time = Time.now
        f.puts "#{log_timestamp} --- REPLICATION STARTED."
        f.flush
        begin
          server_package = manual_server_package || handshake_authenticate(address)
          if server_package
            logger.info "-- HANDSHAKE FINAL PACKAGE: #{server_package.to_yaml}"
            server_result = server_package[:last_synced]
            server_machine_id = server_package[:server_machine_id]
            total_up = run_upload( server_result, server_machine_id, f )
            total_down = run_download( server_machine_id, f )
          else
            f.puts "#{log_timestamp} --- ERROR: PROBLEMS AUTHENTICATION. WRONG USERNAME?"
            f.flush
          end
        rescue Exception => e
          f.puts "#{log_timestamp} --- ERROR: CANNOT REACH SERVER AT #{address}. ERROR: #{e.inspect}"
          f.flush
        end
        end_time = Time.now
        total_time = log_fmt_timestamp(end_time - start_time)
        f.puts "#{log_timestamp} --- REPLICATION FINISHED IN #{total_time} HOURS. #{total_down} RECORDS DOWNLOADED. #{total_up} RECORDS UPLOADED."
        f.flush
      end
    end
  
    def run_dump(manual_server_package = nil, tables_list = [])
      @config = $SYNC_CONFIG
      total_tables = 0
      File.open(SyncsHelper::ReplicatorRunner.log_file, 'a') do |f|
        start_time = Time.now
        f.puts "#{log_timestamp} --- DUMP STARTED."
        f.flush
        begin
          server_package = manual_server_package || handshake_authenticate(address)
          if server_package
            logger.info "-- HANDSHAKE FINAL PACKAGE: #{server_package.to_yaml}"
            tables_list.each do |table_name|
              result_dump = do_get_server_dump(address, table_name)
              if result_dump.errors && result_dump.errors.size > 0
                f.puts "#{log_timestamp} --- ERROR DOWNLOADING FROM #{address}. ERROR: #{result_dump.errors.join("\n")}"
                f.flush                
              end
            end
          else
            f.puts "#{log_timestamp} --- ERROR: PROBLEMS AUTHENTICATION. WRONG USERNAME?"
            f.flush
          end
        rescue Exception => e
          f.puts "#{log_timestamp} --- ERROR: CANNOT REACH SERVER AT #{address}. ERROR: #{e.inspect}"
          f.flush
        end
        end_time = Time.now
        total_time = log_fmt_timestamp(end_time - start_time)
        f.puts "#{log_timestamp} --- DUMP FINISHED IN #{total_time} HOURS. #{total_tables} TABLES DOWNLOADED"
        f.flush
      end
    end
  end
end